home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
TeX 1995 July
/
TeX CD-ROM July 1995 (Disc 1)(Walnut Creek)(1995).ISO
/
dviware
/
dvitovdu32
/
src
/
pascal
/
tek4010vdu.p
< prev
next >
Wrap
Text File
|
1991-11-10
|
11KB
|
325 lines
(* Implements the routines used in VDU-specific modules that emulate
a Tektronix 4010 terminal (VIS500/550, VT640).
The screen is assumed to be 780 pixels high by 1024 pixels wide.
(The actual resolution of an emulating screen may be different, but
such terminals provide automatic scaling.)
The bottom left pixel is the point (x=0,y=0); x coordinates
increase to the right and y coordinates increase up the screen.
DVItoVDU uses a coordinate scheme in which horizontal (=h) coordinates
also increase to the right but vertical (=v) coordinates increase DOWN the
screen, i.e. the top left pixel on the screen is the point (h=0,v=0).
This means that the Tektronix 4010 routines will have to do a
simple translation of the vertical coordinates passed by DVItoVDU.
*)
#include 'globals.h';
#include 'screenio.h';
#include 'tek4010vdu.h';
VAR
oldhiy, (* for remembering old address in SendXY *)
oldhix,
oldloy : INTEGER;
charwidth, (* set by LoadFont and used in ShowChar *)
loadedsize, (* remember alpha size set by last LoadFont; VT640,
VIS500/550 VDUs don't actually need to worry
about this since they use non-TEK4010 fonts to
draw in dialogue region.
VIS240 however uses alpha mode font. *)
charsize : INTEGER; (* used to select alpha character size *)
(******************************************************************************)
PROCEDURE SendXY (x, y : INTEGER);
(* Translates the given screen address into 4 bytes.
havesentxy is used to minimize the number of bytes sent: after the first
4 bytes have been sent, subsequent bytes that don't change need not be sent
(except for the low x byte which is always sent).
If the high x byte changes then the low y byte must also be sent.
*)
VAR hiy, loy, hix, lox : INTEGER;
sendhix : BOOLEAN;
BEGIN
(* we assume y is in [0..maxy] and x is in [0..1023] *)
hiy := ORD(' ') + (y DIV 32);
hix := ORD(' ') + (x DIV 32);
loy := ORD('`') + (y MOD 32);
lox := ORD('@') + (x MOD 32);
IF havesentxy THEN BEGIN
IF hiy <> oldhiy THEN BEGIN
WriteChar(CHR(hiy)); oldhiy := hiy;
END;
sendhix := hix <> oldhix;
IF (loy <> oldloy) OR sendhix THEN BEGIN
WriteChar(CHR(loy)); oldloy := loy;
END;
IF sendhix THEN BEGIN
WriteChar(CHR(hix)); oldhix := hix;
END;
WriteChar(CHR(lox));
END
ELSE BEGIN (* send first 4 bytes *)
WriteChar(CHR(hiy)); oldhiy := hiy;
WriteChar(CHR(loy)); oldloy := loy;
WriteChar(CHR(hix)); oldhix := hix;
WriteChar(CHR(lox));
havesentxy := TRUE;
END;
(* SYSDEP: We assume XON/XOFF flow control is enabled to avoid data loss. *)
END; (* SendXY *)
(******************************************************************************)
PROCEDURE TEK4010StartText;
BEGIN
WriteChar(US);
END; (* TEK4010StartText *)
(******************************************************************************)
PROCEDURE TEK4010MoveToTextLine (line : INTEGER);
(* Move cursor to start of given line using lineht.
At the end of this routine we must be in alpha mode and ready to display
characters in the default charsize.
*)
BEGIN
WriteChar(GS); (* switch to graphics mode *)
SendXY(0,maxy+1 - (line*lineht));
WriteChar(ESC); (* reset alpha character size *)
WriteChar('0');
charsize := 0;
charwidth := 13;
WriteChar(US); (* back to alpha mode *)
END; (* TEK4010MoveToTextLine *)
(******************************************************************************)
PROCEDURE TEK4010ClearScreen;
BEGIN
WriteChar(GS); (* make sure we're in graphics mode *)
WriteChar(ESC); WriteChar(FF); (* erase graphics and put in alpha mode *)
havesentxy := FALSE; (* ESC FF will home cursor *)
charsize := 0; (* ESC FF resets character size *)
charwidth := 13;
END; (* TEK4010ClearScreen *)
(******************************************************************************)
PROCEDURE TEK4010StartGraphics;
BEGIN
IF charsize <> loadedsize THEN BEGIN (* graphics mode was interrupted *)
charsize := loadedsize;
dragdown := (charsize + 1) * 5; (* used by VIS500/550 ShowChar *)
WriteChar(GS);
WriteChar(ESC);
WriteChar(CHR(ORD('0')+charsize)); (* recall last LoadFont character size *)
END;
WriteChar(GS);
havesentxy := FALSE; (* safer to send all bytes anew *)
END; (* TEK4010StartGraphics *)
(******************************************************************************)
PROCEDURE TEK4010LoadFont (fontname : string;
fontsize : INTEGER;
mag, hscale, vscale : REAL);
(* Use the given fontsize to select an appropriate character size
(based on horizontal scaling only!) for future ShowChar calls.
*)
VAR newsize : INTEGER;
BEGIN
(* convert fontsize into scaled screen pixels using mag and hscale *)
fontsize := TRUNC( (fontsize * mag * hscale) + 0.5 );
(* Chooose one of the 4 alpha mode character sizes based on fontsize:
charsize max chars/line relative size fontsize range
0 80 x1 0..40
1 40 x2 41..80
2 26 x3 81..120
3 20 x4 121...
The fontsize ranges were chosen by trial and error.
*)
IF fontsize < 41 THEN BEGIN
newsize := 0;
charwidth := 13; (* 1024/80 = 12.8 *)
END
ELSE IF fontsize < 81 THEN BEGIN
newsize := 1;
charwidth := 26; (* 1024/40 = 25.6 *)
END
ELSE IF fontsize < 121 THEN BEGIN
newsize := 2;
charwidth := 40; (* 1024/26 = 39.4 *)
END
ELSE BEGIN
newsize := 3;
charwidth := 52; (* 1024/20 = 51.2 *)
END;
loadedsize := newsize; (* remember in case graphics mode is interrupted *)
IF charsize <> newsize THEN BEGIN (* change character size *)
charsize := newsize;
WriteChar(ESC);
WriteChar(CHR(ORD('0')+charsize));
END;
(* Alpha character reference pts on some emulating VDUs (VIS500/550) are below
baselines to allow for descenders.
Such VDUs can use dragdown to drag baselines down to TeX reference pts
when calling ShowChar.
*)
dragdown := (charsize + 1) * 5; (* used by VIS500/550 ShowChar *)
WriteChar(GS); (* must exit in graphics mode *)
END; (* TEK4010LoadFont *)
(******************************************************************************)
PROCEDURE TEK4010ShowChar (screenh, screenv : INTEGER;
ch : CHAR);
(* Show the given Terse character (mapped to ASCII) at the given ref pt.
We use the charwidth set by last LoadFont call.
*)
VAR newch : CHAR; (* = TeXtoASCII[ch] *)
BEGIN
(* shift character left if it will overlap right edge of screen *)
IF screenh + charwidth > 1023 THEN
screenh := 1023 - charwidth;
(* we assume StartGraphics, LoadFont or last ShowChar has just sent GS *)
SendXY(screenh,maxy-screenv); (* move cursor to ref pt *)
(* We use TeXtoASCII to map ch into a comparable ASCII character, apart
from most of the ? characters which we attempt to simulate.
*)
WriteChar(US); (* enter alpha mode *)
newch := TeXtoASCII[ch];
IF newch <> '?' THEN
(* newch is similar to TeX ch *)
WriteChar(newch)
ELSE
(* attempt to display something other than ? *)
CASE ORD(ch) OF
13b..17b : (* ff, fi, fl, ffi, ffl *)
BEGIN
WriteChar('f');
(* only simulate rest of ligature if room at right edge *)
IF screenh + 2 * charwidth - (charwidth DIV 2) <= 1023 THEN BEGIN
WriteChar(GS);
SendXY(screenh + charwidth - (charwidth DIV 2),maxy-screenv);
WriteChar(US);
CASE ORD(ch) OF
13b : WriteChar('f') ;
14b : WriteChar('i') ;
15b : WriteChar('l') ;
16b,
17b : BEGIN
WriteChar('f');
IF screenh + 3 * charwidth - 2 * (charwidth DIV 2) <= 1023 THEN
BEGIN
WriteChar(GS);
SendXY(screenh + 2 * charwidth - 2 * (charwidth DIV 2),
maxy-screenv);
WriteChar(US);
IF ch = CHR(16b) THEN
WriteChar('i')
ELSE
WriteChar('l');
END;
END;
END;
END;
END;
31b : WriteChar('B'); (* German sharp S *)
32b, 33b, 35b, 36b : (* diphthongs: ae, oe, AE, OE *)
BEGIN
CASE ORD(ch) OF
32b : WriteChar('a') ;
33b : WriteChar('o') ;
35b : WriteChar('A') ;
36b : WriteChar('O')
END;
IF screenh + 2 * charwidth - (charwidth DIV 2) <= 1023 THEN BEGIN
WriteChar(GS);
SendXY(screenh + charwidth - (charwidth DIV 2),maxy-screenv);
WriteChar(US);
CASE ORD(ch) OF
32b, 33b : WriteChar('e') ;
35b, 36b : WriteChar('E')
END;
END;
END;
34b, 37b : (* Scandinavian slashed o and O *)
BEGIN
CASE ORD(ch) OF
34b : WriteChar('o') ;
37b : WriteChar('O')
END;
WriteChar(GS);
SendXY(screenh,maxy-screenv); (* overwrite *)
WriteChar(US);
WriteChar('/');
END;
40b : WriteChar(''''); (* Polish suppressed l and L *)
OTHERWISE
WriteChar('?');
END;
WriteChar(GS); (* must exit in graphics mode *)
END; (* TEK4010ShowChar *)
(******************************************************************************)
PROCEDURE TEK4010ShowRectangle (screenh, screenv, (* top left pixel *)
width, height : INTEGER; (* of rectangle *)
ch : CHAR); (* black pixel *)
(* Display the given rectangle (without using the given black pixel character).
DVItoVDU ensures that the top left position is visible and that the given
dimensions do not go beyond the window edges.
*)
VAR i, endpt : INTEGER;
BEGIN
(* DVItoVDU ensures width and height > 0 *)
IF height < width THEN BEGIN (* show row vectors *)
endpt := screenh+width-1;
FOR i := 0 TO height-1 DO BEGIN
WriteChar(GS);
SendXY(screenh,maxy-(screenv+i)); (* move cursor to start of row *)
SendXY(endpt,maxy-(screenv+i)); (* draw vector to end of row *)
END;
END
ELSE BEGIN (* show column vectors *)
endpt := maxy - (screenv+height-1);
FOR i := 0 TO width-1 DO BEGIN
WriteChar(GS);
SendXY(screenh+i,maxy-screenv); (* move cursor to start of column *)
SendXY(screenh+i,endpt); (* draw vector to end of column *)
END;
END;
END; (* TEK4010ShowRectangle *)
(******************************************************************************)
PROCEDURE InitTEK4010VDU;
BEGIN
havesentxy := FALSE; (* for first SendXY call *)
charsize := 0; (* the default character size *)
loadedsize := charsize; (* for first StartGraphics call *)
charwidth := 13; (* 1024 / 80 = 12.8 *)
maxy := 779; (* some VDUs may want to change this *)
lineht := 26; (* 30 text lines; 26 * 30 = 780 *)
END; (* InitTEK4010VDU *)